<?php

declare(strict_types=1);

namespace base\common\command\admin;

use think\console\Command;
use think\console\Input;
use think\console\Output;

class MigrateFileDataBase extends Command
{
    /**
     * 要检测的模型路径，一般以app开头或其他模块开头，不支持多级目录.
     *
     * @var array
     */
    protected $modelPath = [
        'app/admin/model',
    ];

    /**
     * 老的域名，准备替换的域名，如果不以http:// 或 https:// 开头，会自动添加并尝试替换两种协议
     * 一般只填写域名或者IP端口.
     *
     * @var array
     */
    protected $fromDomain = [
        '127.0.0.1:8000',
    ];

    /**
     * 新的文件域名，必须以http:// 或 https:// 开头.
     *
     * @var string
     */
    protected $toDomain = '';

    protected function configure()
    {
        // 指令配置
        $this->setName('admin:migrate:file:data')
            ->setDescription('将数据库中的文件地址从老地址更新到新地址，只处理数据库数据，不会实际迁移文件');
    }

    protected function execute(Input $input, Output $output)
    {
        if (empty($this->toDomain)) {
            $output->error('请指定新的文件域名');

            return;
        }

        $this->fromDomain = array_filter($this->fromDomain, function ($domain) {
            return !empty($domain);
        });

        if (empty($this->fromDomain)) {
            $output->error('请指定老的域名');

            return;
        }

        // 指令输出
        $model_files = [];

        foreach ($this->modelPath as $model_path) {
            $model_files = array_merge($model_files, glob($model_path . '/*.php'));
        }

        $model_class = [];

        foreach ($model_files as $file) {
            $class_name = str_replace('.php', '', $file);
            $class_name = str_replace('/', '\\', $class_name);
            $model_class[] = $class_name;
        }

        $field_map = [];

        foreach ($model_class as $class_name) {
            if (!isset($field_map[$class_name])) {
                $field_map[$class_name] = [];
            }
            $field_list_file = $class_name::FIELD_LIST_FILE;
            if (!empty($field_list_file)) {
                $field_map[$class_name] = array_merge($field_map[$class_name], $field_list_file);
            }

            $field_list_content = $class_name::FIELD_LIST_CONTENT;
            if (!empty($field_list_content)) {
                $field_map[$class_name] = array_merge($field_map[$class_name], $field_list_content);
            }
        }

        $field_map = array_filter($field_map);

        foreach ($field_map as $model_class => $field_list) {
            $output->writeln("开始处理 {$model_class}");
            $model_cursor = $model_class::cursor();
            foreach ($model_cursor as $modle_item) {
                foreach ($field_list as $field_name) {
                    $field_value = $modle_item->{$field_name};
                    $new_field_value = $this->replaceDomain($field_value);
                    if ($field_value != $new_field_value) {
                        $modle_item->{$field_name} = $new_field_value;
                        $modle_item->save();
                        $output->writeln("{$model_class} - {$field_name} - {$field_value} => {$new_field_value}");
                    }
                }
            }
        }
    }

    private function replaceDomain($field_value)
    {
        if (empty($field_value)) {
            return $field_value;
        }

        $from_domain_list = [];
        foreach ($this->fromDomain as $from_domain) {
            if (!str_starts_with($from_domain, 'http://') && !str_starts_with($from_domain, 'https://')) {
                $from_domain_list[] = 'http://' . $from_domain;
                $from_domain_list[] = 'https://' . $from_domain;
            } else {
                $from_domain_list[] = $from_domain;
            }
        }

        $to_domain = $this->toDomain;
        $field_value = str_replace($from_domain_list, $to_domain, $field_value);

        return $field_value;
    }
}
